package com.example.java_doc_searcher.searcher;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.ansj.domain.Term;
import org.ansj.splitWord.analysis.ToAnalysis;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Index {
    private static String INDEX_PATH = null;

    static {
        if (Config.isOnline) {
            INDEX_PATH = "/home/ubuntu/install/doc_searcher_index/";
        } else {
            INDEX_PATH = "D:\\doc_searcher_index\\";
        }
    }
    private ObjectMapper objectMapper = new ObjectMapper();
    private ArrayList<DocInfo> forwardIndex = new ArrayList<>();
    private HashMap<String,ArrayList<Weight>> invertedIndex = new HashMap<>();
    private Object locker1 = new Object();
    private Object locker2= new Object();
    public DocInfo getDocInfo(int docId){

        return forwardIndex.get(docId);
    }
    public List<Weight> getInverted(String term){
        return invertedIndex.get(term);
    }
    public void addDoc(String title,String url,String content){
        DocInfo docInfo = buildForward(title,url,content);
        buildInverted(docInfo);

    }

    private void buildInverted(DocInfo docInfo) {
        class WordCnt{
            public int titleCount;
            public int contentCount;
        }
        HashMap<String,WordCnt> wordCntHashMap = new HashMap<>();
      List<Term> terms =  ToAnalysis.parse(docInfo.getTitle()).getTerms();
      for(Term term:terms){
          String word =term.getName();
          WordCnt wordCnt = wordCntHashMap.get(word);
          if(wordCnt ==null){
              WordCnt newWordCnt = new WordCnt();
              newWordCnt.titleCount = 1;
              newWordCnt.contentCount = 0;
              wordCntHashMap.put(word,newWordCnt);


          }else{
              wordCnt.titleCount +=1;
          }


      }
      terms = ToAnalysis.parse(docInfo.getContent()).getTerms();
        for(Term term:terms) {
            String word = term.getName();
            WordCnt wordCnt = wordCntHashMap.get(word);
            if (wordCnt == null) {
                WordCnt newWordCnt = new WordCnt();
                newWordCnt.titleCount = 0;
                newWordCnt.contentCount = 1;
                wordCntHashMap.put(word, newWordCnt);


            } else {
                wordCnt.contentCount += 1;
            }
        }
      for(Map.Entry<String,WordCnt>entry:wordCntHashMap.entrySet()){
          synchronized(locker2) {
              List<Weight> invertedList = invertedIndex.get(entry.getKey());
              if (invertedList == null) {
                  ArrayList<Weight> newInvertedList = new ArrayList<>();
                  Weight weight = new Weight();
                  weight.setDocId(docInfo.getDocId());
                  weight.setWeight(entry.getValue().titleCount * 10 + entry.getValue().contentCount);
                  newInvertedList.add(weight);
                  invertedIndex.put(entry.getKey(), newInvertedList);
              } else {
                  Weight weight = new Weight();
                  weight.setDocId(docInfo.getDocId());
                  weight.setWeight(entry.getValue().titleCount * 10 + entry.getValue().contentCount);
                  invertedList.add(weight);
              }
          }
      }
    }

    private DocInfo buildForward(String title, String url, String content) {
        DocInfo docInfo = new DocInfo();

        docInfo.setTitle(title);
        docInfo.setUrl(url);
        docInfo.setContent(content);
        synchronized (locker1){
        docInfo.setDocId(forwardIndex.size());
        forwardIndex.add(docInfo);}
        return docInfo;

    }


    public void save(){
       long beg = System.currentTimeMillis();
        File indexPathFile =new File(INDEX_PATH);
        if(!indexPathFile.exists()){
            indexPathFile.mkdirs();
        }
        File forwardIndexFile =new File(INDEX_PATH+"forward.txt");
        File invertedIndexFile = new File(INDEX_PATH+"inverted.txt");
        try{

            objectMapper.writeValue(forwardIndexFile,forwardIndex);
            objectMapper.writeValue(invertedIndexFile,invertedIndex);
        }catch(IOException e){
            e.printStackTrace();

        }
        long end =System.currentTimeMillis();
        System.out.println("保存索引完成!消耗时间"+(end-beg)+"ms");
    }
    public void load(){
        long beg = System.currentTimeMillis();
        System.out.println("加载索引开始");
        File forwardIndexFile =new File(INDEX_PATH+"forward.txt");
        File invertedIndexFile = new File(INDEX_PATH+"inverted.txt");
        try{
            forwardIndex = objectMapper.readValue(forwardIndexFile, new TypeReference<ArrayList<DocInfo>>() {
            });
            invertedIndex = objectMapper.readValue(invertedIndexFile, new TypeReference<HashMap<String, ArrayList<Weight>>>() {
            });
        }catch(IOException e){
                e.printStackTrace();
            }
        long end =System.currentTimeMillis();
        System.out.println("保护索引结束!消耗时间"+(end-beg)+"ms");
        }
    public static void main(String[] args) {
        Index index = new Index();
        index.load();
        System.out.println("索引制作完成");

    }

    }


